package com.inspector.app.util;

import android.annotation.SuppressLint;
import android.content.Context;
import android.location.LocationManager;
import android.text.TextUtils;

import androidx.core.location.LocationManagerCompat;


import com.mapsforge.map.EfbLatLngPoint;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

/**
 * @author zlq
 * @date 2019/8/12
 */
public class LocationUtils {
    /**
     * 度转度分秒
     *
     * @param loc
     * @return
     */
    @SuppressLint("DefaultLocale")
    public static String D2Dms(double loc) {
        int d = 0;
        int m = 0;
        double s = 0;

        String second = "0";
        try {
            d = (int) loc;
            m = (int) ((loc - d) * 60);
            s = ((loc - d - (double) m / 60) * 3600);

            //[移除小数点后无效的0]
            second = CommonUtil.convertByBigDecimal(String.format("%.1f", s).trim());
        } catch (Exception e) {
            e.printStackTrace();
            return String.valueOf(loc);
        }
        return d + "°" + m + "′" + second + "″";
    }

    /**
     * 度转度分秒
     *
     * @param loc
     * @return
     */
    @SuppressLint("DefaultLocale")
    public static String[] D2DmsStrs(double loc) {
        int d = 0;
        int m = 0;
        String second = "0";
        try {
            d = (int) loc;
            m = (int) ((loc - d) * 60);
            double s = new BigDecimal((loc - d - (double) m / 60) * 3600).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

            //[移除小数点后无效的0]
            second = CommonUtil.convertByBigDecimal(String.format("%.1f", s).trim());
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return new String[]{String.valueOf(loc), "", ""};
        }
//        LogUtil.e("D2DmsStrs","second："+second);
        return new String[]{String.valueOf(d), String.valueOf(m), second};
    }

    @SuppressLint("DefaultLocale")
    public static String[] D2DmsStrs(double loc, String format) {
        int d = 0;
        int m = 0;
        String second = "0";
        try {
            d = (int) loc;
            m = (int) ((loc - d) * 60);

            double s = new BigDecimal((loc - d - (double) m / 60) * 3600).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            if (s == 60) {
                s = 0;
                m = m + 1;
                if (m == 60) {
                    m = 0;
                    d = d + 1;
                }
            } else {
                second = new BigDecimal(s).stripTrailingZeros().toPlainString();
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return new String[]{String.valueOf(loc), "", ""};
        }
        return new String[]{String.valueOf(d), String.valueOf(m), second};
    }


    /**
     * 度转度分
     *
     * @param loc
     * @return
     */
    public static String D2Dm(double loc) {
        int d = 0;
        double m = 0;
        try {
            d = (int) loc;
            m = ((loc - d) * 60);
            if (m > 60) {
                ToastUtil.getInstance().showToast("度分秒格式中，分值不应超过60！");
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return String.valueOf(loc);
        }
        return d + "°" + String.format("%.3f", m) + "′";
    }

    public static String D2Dm(double loc, String format) {
        int d = 0;
        double m = 0;
        try {
            d = (int) loc;
            m = ((loc - d) * 60);
            if (m > 60) {
                ToastUtil.getInstance().showToast("度分秒格式中，分值不应超过60！");
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return String.valueOf(loc);
        }
        return d + "°" + String.format(format, m) + "′";
    }

    //度转度分
    public static String D2Dmms(double loc) {
        int d = 0;
        double m = 0;
        try {
            d = (int) loc;
            m = ((loc - d) * 60);
            if (m > 60) {
                ToastUtil.getInstance().showToast("度分秒格式中，分值不应超过60！");
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return String.valueOf(loc);
        }
        return d + "°" + String.format("%.3f", m);
    }


    /**
     * 将度分转换为度分秒格式
     */
    public static double[] transform_dms(double degree, double minute) {
        int d = (int) degree;
        double m = (degree - d) * 60 + minute;
        d += (int) (m / 60);
        double m2 = m % 60;
        m = (int) m2;
        if (m > 60) {
            ToastUtil.getInstance().showToast("分值不应超过60！");
        }
        double s = (m2 - m) * 60;
        return new double[]{d, m, s};
    }

    /**
     * 度分转经纬度
     */
    public static double df2LatLng(String dm) {
        if (dm == null) {
            return 0;
        }
        try {
            dm = dm.replace(" ", "");
            int d = parseInteger(dm.substring(0, dm.lastIndexOf(".") - 2));
            // 兼容经纬度的转换
            double fen = Double.parseDouble(dm.substring(String.valueOf(d).length()));

            double lat = (fen / 60) + Math.abs(d);
            if (lat < 0) {
                lat = -lat;
            }
            return Double.parseDouble(String.format("%.7f", lat));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    public static double df2LatLng(String dm, String format) {
        if (dm == null) {
            return 0;
        }
        try {
            dm = dm.replace(" ", "");
            int d = parseInteger(dm.substring(0, dm.lastIndexOf(".") - 2));
            // 兼容经纬度的转换
            double fen = Double.parseDouble(dm.substring(String.valueOf(d).length()));

            double lat = (fen / 60) + Math.abs(d);
            if (lat < 0) {
                lat = -lat;
            }
            return Double.parseDouble(String.format(format, lat));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }


    public static Integer parseInteger(String str) {
        if (str == null || str.isEmpty()) {
            return 0;
        }
        return Integer.valueOf(str);
    }

    /**
     * 度分秒转度
     *
     * @return
     */
    public static double Dms2D(String dStr, String mStr, String sStr) {
        double d = 0;
        try {
            d = Double.parseDouble(dStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        double m = 0;
        try {
            m = Double.parseDouble(mStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        double s = 0;
        try {
            s = Double.parseDouble(sStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (m > 60) {
            ToastUtil.getInstance().showToast("度分秒格式中，分值不应超过60！");
        }
        if (s > 60) {
            ToastUtil.getInstance().showToast("度分秒格式中，秒值不应超过60！");
        }
        return d + m / 60 + s / 60 / 60;
    }

    /**
     * 度分秒转度
     *
     * @return
     */
    public static double Dms2D(double d, double m, double s) {
        return d + m / 60 + s / 60 / 60;
    }


    public static EfbLatLngPoint getCenterOfPoints(List<EfbLatLngPoint> efbLatLngPoints) {

        if (null == efbLatLngPoints || efbLatLngPoints.isEmpty()) {
            return null;
        }

        int size = efbLatLngPoints.size();

        double lng = 0, lat = 0;
        for (EfbLatLngPoint ePoint : efbLatLngPoints) {
            lat = lat + ePoint.lat;
            lng = lng + ePoint.lng;
        }
        return new EfbLatLngPoint(lat / size, lng / size);
    }

    /**
     * 度分秒格式字符串 转成double 类型小数形式坐标
     *
     * @param latlng
     * @param isLatitude 是否是纬度
     * @return
     */
    public static double getLatLngDouble(String latlng, boolean isLatitude) {

        if (latlng.contains("度")) {

            latlng = latlng.replaceAll("度", "°").replaceAll("分", "′").replaceAll("秒", "″");
        }
        String degree = null;
        String minute = null;
        String second = null;
        String[] split = latlng.split("°");
//        String[] split1 = latlng.split("′");
//        String[] split2 = latlng.split("″");
//        Log.i("feifei",split.length+"=split=="+new Gson().toJson(split)); //1=split==["33"]
//        Log.i("feifei",split1.length+"split1"+new Gson().toJson(split1)); //1split1["33°"]
//        Log.i("feifei","split2"+new Gson().toJson(split2));
        if (null != split[0]) {
            degree = split[0];
        }
        if (split.length > 1) {
            if (split[1].contains("′")) {
                String[] split1 = split[1].split("′");
                if (null != split1[0]) {
                    minute = split1[0];
                }
                if (split1.length > 1) {
                    if (split1[1].contains("″")) {
                        second = split1[1].split("″")[0];
                    }

                }
            }
        }
        return Dms2D(degree, minute, second, isLatitude);
    }

    /**
     * 度分秒转度
     *
     * @return
     */
    public static double Dms2D(String dStr, String mStr, String sStr, boolean isLatitude) {

        double d = 0;
        double m = 0;
        double s = 0;
        try {
            d = Double.parseDouble(dStr);
            if (null != mStr) {
                m = Double.parseDouble(mStr);
            }
            if (null != sStr) {
                s = Double.parseDouble(sStr);
            }


            if (m >= 60 || s >= 60) {
                ToastUtil.getInstance().showToast("分/秒输入错误！");
                return 0;
            }

            if ((isLatitude && d >= 90) || (isLatitude && d >= 180)) {
                ToastUtil.getInstance().showToast("度输入错误！");
                return 0;
            }


        } catch (NumberFormatException e) {
            ToastUtil.getInstance().showToast("输入错误！");
            return 0;
        }
        return d + m / 60 + s / 60 / 60;
    }

    /**
     * 度分秒格式字符串 转成double 类型小数形式坐标
     *
     * @param latlng
     * @return
     */
    public static double getLatLngDouble(String latlng) {
        try {
            if (TextUtils.isEmpty(latlng) || Objects.equals(latlng, "---")) return 0; //"---"
            latlng = latlng.replaceAll("度", "°").replaceAll("分", "′").replaceAll("秒", "″");

            String[] split = latlng.split("°");
            String degree = split[0];

            String[] split1 = split[1].split("′");

            String minute = split1[0];

            String second = split1[1].split("″")[0];

            return Dms2D(degree, minute, second);
        } catch (Exception e) {
//            e.printStackTrace();
        }
        return 0;
    }

    public static double pi = 3.1415926535897932384626;
    public static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
    public static double a = 6378245.0;
    public static double ee = 0.00669342162296594323;


    public static double TransformLat(double x, double y) {
        double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y
                + 0.2 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
        return ret;
    }


    public static double TransformLon(double x, double y) {
        double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
                * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
                * pi)) * 2.0 / 3.0;
        return ret;
    }


    public static double[] transform(double lat, double lon) {
        if (OutOfChina(lat, lon)) {
            return new double[]{lat, lon};
        }
        double dLat = TransformLat(lon - 105.0, lat - 35.0);
        double dLon = TransformLon(lon - 105.0, lat - 35.0);
        double radLat = lat / 180.0 * pi;
        double magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        double SqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * SqrtMagic) * pi);
        dLon = (dLon * 180.0) / (a / SqrtMagic * Math.cos(radLat) * pi);
        double mgLat = lat + dLat;
        double mgLon = lon + dLon;
        return new double[]{mgLat, mgLon};
    }


    public static boolean OutOfChina(double lat, double lon) {
        if (lon < 72.004 || lon > 137.8347)
            return true;
        if (lat < 0.8293 || lat > 55.8271)
            return true;
        return false;
    }


    /**
     * 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System
     *
     * @param lat
     * @param lon
     * @return
     */
    public static double[] Gps84ToGcj02(double lat, double lon) {
        if (OutOfChina(lat, lon)) {
            return new double[]{lat, lon};
        }
        double dLat = TransformLat(lon - 105.0, lat - 35.0);
        double dLon = TransformLon(lon - 105.0, lat - 35.0);
        double radLat = lat / 180.0 * pi;
        double magic = Math.sin(radLat);
        magic = 1 - ee * magic * magic;
        double SqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * SqrtMagic) * pi);
        dLon = (dLon * 180.0) / (a / SqrtMagic * Math.cos(radLat) * pi);
        double mgLat = lat + dLat;
        double mgLon = lon + dLon;
        return new double[]{mgLat, mgLon};
    }


    /**
     * * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return
     */
    public static double[] Gcj02ToGps84(double lat, double lon) {
        double[] gps = transform(lat, lon);
        double lontitude = lon * 2 - gps[1];
        double latitude = lat * 2 - gps[0];
        return new double[]{latitude, lontitude};
    }

    /// <summary>
    /// 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标
    /// 高德谷歌转为百度
    /// </summary>
    /// <param name="lat"></param>
    /// <param name="lon"></param>
    /// <returns></returns>
    public static double[] Gcj02ToBd09(double lat, double lon) {
        double x = lon, y = lat;
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
        double tempLon = z * Math.cos(theta) + 0.0065;
        double tempLat = z * Math.sin(theta) + 0.006;
        double[] gps = {tempLat, tempLon};
        return gps;
    }


    /// <summary>
    /// 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标
    /// 百度坐标转为高德谷歌坐标
    /// </summary>
    /// <param name="lat"></param>
    /// <param name="lon"></param>
    /// <returns></returns>
    public static double[] Bd09ToGcj02(double lat, double lon) {
        double x = lon - 0.0065, y = lat - 0.006;
        double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
        double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
        double tempLon = z * Math.cos(theta);
        double tempLat = z * Math.sin(theta);
        double[] gps = {tempLat, tempLon};
        return gps;
    }


    /// <summary>
    /// gps84转为bd09
    /// GPS坐标转为百度坐标
    /// </summary>
    /// <param name="lat"></param>
    /// <param name="lon"></param>
    /// <returns></returns>
    public static double[] Gps84ToBd09(double lat, double lon) {
        double[] gcj02 = Gps84ToGcj02(lat, lon);
        double[] bd09 = Gcj02ToBd09(gcj02[0], gcj02[1]);
        return bd09;
    }

    /// <summary>
    /// 百度坐标转成GPS坐标
    /// </summary>
    /// <param name="lat"></param>
    /// <param name="lon"></param>
    /// <returns></returns>
    public static double[] Bd09ToGps84(double lat, double lon) {
        double[] gcj02 = Bd09ToGcj02(lat, lon);
        double[] gps84 = Gcj02ToGps84(gcj02[0], gcj02[1]);
        //保留小数点后六位
        gps84[0] = Retain6(gps84[0]);
        gps84[1] = Retain6(gps84[1]);
        return gps84;
    }


    /// <summary>
    /// 保留小数点后六位
    /// </summary>
    /// <param name="num"></param>
    /// <returns></returns>
    private static double Retain6(double num) {
        String result = String.format("%.6f", num);
        return Double.parseDouble(result);
    }



}
